#if defined(TSINGMA_MX) || defined(TSINGMA_GX)
/**
 @file sys_tmm_port.c

 @date 2020-1-9

 @version v1.0

 The file contains TMM port APIs of sys layer
*/

/***************************************************************
 *
 * Header Files
 *
 ***************************************************************/
#include "ctc_error.h"
#include "sys_usw_port.h"
#include "sys_usw_chip.h"
#include "sys_usw_dmps.h"

#define SYS_PORT_CS_MAC_ID_START   80
#define SYS_PORT_DATA_READY        0x10
#define SYS_PORT_DATA_CHECK_FAIL   0x1
#define SYS_PORT_PRIO_CLASS_NUM     8

/**
@brief Config pause's speed
*/
int32
sys_tmm_port_set_pause_speed(uint8 lchip, uint32 mac_id, void* p_data)
{
    uint32 cmd = 0;
    uint32 pause_dec_value = 0;
    uint32 pause_pulse_sel = 0;
    uint16 step = 0;
    sys_usw_port_mac_config_t* port_mac_config = (sys_usw_port_mac_config_t*)p_data;
    McMacPauseRxCtl_m mac_rx_pause_ctl;
    McMacPauseTxCtl_m mac_tx_pause_ctl;
    ds_t ds;

    CTC_MAX_VALUE_CHECK(mac_id, SYS_CPU_MAC_ID_MAX);
    switch (port_mac_config->speed_mode)
    {
        case CTC_PORT_SPEED_1G:
            pause_dec_value = 2;
            pause_pulse_sel = 1;
           break;
        case CTC_PORT_SPEED_2G5:
            pause_dec_value = 5;
            pause_pulse_sel = 1;
            break;
        case CTC_PORT_SPEED_10G:
            pause_dec_value = 10;
            break;
        case CTC_PORT_SPEED_20G:
            pause_dec_value = 20;
            break;
        case CTC_PORT_SPEED_40G:
            pause_dec_value = 40;
            break;
        case CTC_PORT_SPEED_100G:
            pause_dec_value = 100;
            break;
        case CTC_PORT_SPEED_5G:
            pause_dec_value = 5;
            break;
        case CTC_PORT_SPEED_25G:
            pause_dec_value = 25;
            break;
        case CTC_PORT_SPEED_50G:
            pause_dec_value = 50;
            break;
        case CTC_PORT_SPEED_200G:
            pause_dec_value = 200;
            break;
        case CTC_PORT_SPEED_400G:
            pause_dec_value = 200;
            pause_pulse_sel = 2;
            break;
        default:
            pause_dec_value = 10;
            break;
    }

    if(port_mac_config->interface_type ==  CTC_PORT_IF_FLEXE)
    {
        if (port_mac_config->speed_value >= 400)
        {
            pause_dec_value = port_mac_config->speed_value / 2;
            pause_pulse_sel = 2;
        }
        else if (port_mac_config->speed_value >= 5)
        {
            pause_dec_value = port_mac_config->speed_value;
            pause_pulse_sel = 0;
        }
    }

    if (DRV_IS_TMG(lchip))
    {
		uint16 index = 0;
#ifdef EMULATION_ENV
        if(mac_id >= SYS_CPU_MAC_ID_MIN && mac_id <= SYS_CPU_MAC_ID_MAX) return CTC_E_NONE;
#endif
        step = (Sgmac1RxPauseCfg_t - Sgmac0RxPauseCfg_t) * (mac_id % MCHIP_CAP(SYS_CAP_STATS_XQMAC_PORT_NUM));
        index = mac_id / MCHIP_CAP(SYS_CAP_STATS_XQMAC_PORT_NUM);
        cmd = DRV_IOR(Sgmac0RxPauseCfg_t + step, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds));
        SetSgmac0RxPauseCfg(V, cfgSgmac0RxPauseTimerDecValue_f, &ds, pause_dec_value);
        if(port_mac_config->is_init)
        {
            /*Default disable flow ctl*/
            SetSgmac0RxPauseCfg(V, cfgSgmac0RxNormPauseEn_f + step, &ds, 0);
            SetSgmac0RxPauseCfg(V, cfgSgmac0RxPfcPriorityEn_f + step, &ds, 0);
        }
        cmd = DRV_IOW(Sgmac0RxPauseCfg_t + step, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds));

        step = (Sgmac1TxPauseCfg_t - Sgmac0TxPauseCfg_t) * (mac_id % MCHIP_CAP(SYS_CAP_STATS_XQMAC_PORT_NUM));
        cmd = DRV_IOR(Sgmac0TxPauseCfg_t + step, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds));
        SetSgmac0TxPauseCfg(V, cfgSgmac0TxPauseTimerDecValue_f, &ds, pause_dec_value);
        SetSgmac0TxPauseCfg(V, cfgSgmac0TxPauseTimerAdjValue_f, &ds, 0xFF00);/*for pressure flow to 0 */
        cmd = DRV_IOW(Sgmac0TxPauseCfg_t + step, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds));

        step = QuadSgmacCfg_cfgSgmac1PausePulseSel_f - QuadSgmacCfg_cfgSgmac0PausePulseSel_f;
        cmd = DRV_IOR(QuadSgmacCfg_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds));
        SetQuadSgmacCfg(V, cfgSgmac0PausePulseSel_f + step * (mac_id % MCHIP_CAP(SYS_CAP_STATS_XQMAC_PORT_NUM)), &ds, pause_pulse_sel);
        cmd = DRV_IOW(QuadSgmacCfg_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds));

        return CTC_E_NONE;
    }
    if (mac_id >= SYS_CPU_MAC_ID_MIN && mac_id <= SYS_CPU_MAC_ID_MAX)
    {
        step = (Sgmac1RxPauseCfg_t - Sgmac0RxPauseCfg_t) * (mac_id - SYS_CPU_MAC_ID_MIN);
        cmd = DRV_IOR(Sgmac0RxPauseCfg_t + step, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
        SetSgmac0RxPauseCfg(V, cfgSgmac0RxPauseTimerDecValue_f, &ds, pause_dec_value);
        cmd = DRV_IOW(Sgmac0RxPauseCfg_t + step, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));

        step = (Sgmac1TxPauseCfg_t - Sgmac0TxPauseCfg_t) * (mac_id - SYS_CPU_MAC_ID_MIN);
        cmd = DRV_IOR(Sgmac0TxPauseCfg_t + step, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
        SetSgmac0TxPauseCfg(V, cfgSgmac0TxPauseTimerDecValue_f, &ds, pause_dec_value);
        SetSgmac0TxPauseCfg(V, cfgSgmac0TxPauseTimerAdjValue_f, &ds, 0xFF00);/*for pressure flow to 0 */
        cmd = DRV_IOW(Sgmac0TxPauseCfg_t + step, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
    }
    else
    {
        cmd = DRV_IOR(McMacPauseRxCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, mac_id / MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM), cmd, &mac_rx_pause_ctl));    
        cmd = DRV_IOR(McMacPauseTxCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, mac_id / MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM), cmd, &mac_tx_pause_ctl));
   
        step = (McMacPauseRxCtl_mcMacPauseRxCfg_1_cfgMcMacRxPauseTimerDecValue_f - McMacPauseRxCtl_mcMacPauseRxCfg_0_cfgMcMacRxPauseTimerDecValue_f)
                * (mac_id % MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM));
        SetMcMacPauseRxCtl(V, mcMacPauseRxCfg_0_cfgMcMacRxPauseTimerDecValue_f + step, &mac_rx_pause_ctl, pause_dec_value);
        if(port_mac_config->is_init)
        {
            /*Default disable flow ctl*/
            SetMcMacPauseRxCtl(V, mcMacPauseRxCfg_0_cfgMcMacRxNormPauseEn_f + step, &mac_rx_pause_ctl, 0);
            SetMcMacPauseRxCtl(V, mcMacPauseRxCfg_0_cfgMcMacRxPfcPriorityEn_f + step, &mac_rx_pause_ctl, 0);
        }
        /*(adj/dec)*pulse_time < quanta * 512bit_time*/
        step = (McMacPauseTxCtl_mcMacPauseTxCfg_1_cfgMcMacTxPauseTimerDecValue_f - McMacPauseTxCtl_mcMacPauseTxCfg_0_cfgMcMacTxPauseTimerDecValue_f)
                * (mac_id % MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM));
        SetMcMacPauseTxCtl(V, mcMacPauseTxCfg_0_cfgMcMacTxPauseTimerDecValue_f + step, &mac_tx_pause_ctl, pause_dec_value);
        SetMcMacPauseTxCtl(V, mcMacPauseTxCfg_0_cfgMcMacTxPauseTimerAdjValue_f + step, &mac_tx_pause_ctl, 0xFF00);/*for pressure flow to 0 */
        SetMcMacPauseTxCtl(V, mcMacPauseTxCfg_0_cfgMcMacPausePulseSel_f + step, &mac_tx_pause_ctl, pause_pulse_sel);

        cmd = DRV_IOW(McMacPauseRxCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, mac_id / MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM), cmd, &mac_rx_pause_ctl));
        cmd = DRV_IOW(McMacPauseTxCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, mac_id / MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM), cmd, &mac_tx_pause_ctl));
    }
    return CTC_E_NONE;
}

int32
_sys_tmm_port_flow_ctrl_cfg(uint8 lchip)
{
    uint8 gchip_id = 0;
    uint32 cmd = 0;
    uint32 mac_id = 0;
    uint16 lport = 0;
    uint32 value = 0;
    uint32 time = 1000;
    uint16 chan_id = 0;
    DsIrmPortStallEn_m  irm_stall_en;
    ds_t ds;
    uint8 speed_mode[324]; /*MCHIP_CAP(SYS_CAP_MAC_NUM_PER_DP) * 2 + cpumacnum*/
    sys_usw_dmps_port_info_t dmps_port_info = {0};
    sys_usw_port_mac_config_t port_mac_config = {0};

    sal_memset(&ds, 0, sizeof(ds));
    sal_memset(&irm_stall_en, 0, sizeof(DsIrmPortStallEn_m));
    sal_memset(speed_mode, 0xFF, sizeof(speed_mode));

    if (DRV_CHIP_SUB_TYPE_4 == DRV_CHIP_SUB_TYPE(lchip))
    {
        cmd = DRV_IOR(MiscIntInfo2_t, DRV_ENTRY_FLAG);
        while (--time)
        {
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
            if (SYS_PORT_DATA_READY == (GetMiscIntInfo0(V,miscIntInfo0_f, &ds) & SYS_PORT_DATA_READY))
            {
                break;
            }
            sal_task_sleep(10);
        }
        if (0 == time)
        {
            SYS_PORT_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "RISC-V execute timeout\n");
            return CTC_E_HW_TIME_OUT;
        }
        if (SYS_PORT_DATA_CHECK_FAIL == (GetMiscIntInfo0(V,miscIntInfo0_f, &ds) & SYS_PORT_DATA_CHECK_FAIL))
        {
            return CTC_E_HW_FAIL;
        }
    }

    for (chan_id = 0; chan_id < MCHIP_CAP(SYS_CAP_CHANNEL_NUM); chan_id++)
    {
        cmd = DRV_IOW(DsIrmPortStallEn_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, chan_id, cmd, &irm_stall_en);
    }

    CTC_ERROR_RETURN(sys_usw_get_gchip_id(lchip, &gchip_id));
    for (lport = 0; lport < MCHIP_CAP(SYS_CAP_PER_SLICE_PORT_NUM); lport++)
    {
        dmps_port_info.gport = CTC_MAP_LPORT_TO_GPORT(gchip_id, lport);
        CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_PORT_TYPE, (void *)&value));
        if ((SYS_DMPS_NETWORK_PORT != value) && (SYS_DMPS_CPUMAC_NETWORK_PORT != value))
        {
            continue;
        }
        CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_MAC_ID, (void *)&mac_id));
        CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_SPEED_MODE, (void *)&value));
        speed_mode[mac_id] = value;
    }

    port_mac_config.is_init = 1;
    for (mac_id = 0; mac_id < (MCHIP_CAP(SYS_CAP_MAC_NUM_PER_DP)+MCHIP_CAP(SYS_CAP_CPUMAC_NUM_PER_DP))*MCHIP_CAP(SYS_CAP_DP_MAX_NUM); mac_id++)
    {
        if (DRV_CHIP_SUB_TYPE_4 == DRV_CHIP_SUB_TYPE(lchip) && (mac_id < SYS_PORT_CS_MAC_ID_START || 
          (mac_id >= MCHIP_CAP(SYS_CAP_MAC_NUM_PER_DP) && mac_id < SYS_PORT_CS_MAC_ID_START + MCHIP_CAP(SYS_CAP_MAC_NUM_PER_DP))))
        {
            continue;
        }
        port_mac_config.speed_mode = speed_mode[mac_id];
        CTC_ERROR_RETURN(sys_tmm_port_set_pause_speed(lchip, mac_id, (void*)&port_mac_config));
    }

    return CTC_E_NONE;
}

int32
sys_tmm_port_flow_ctl_init(uint8 lchip)
{
    uint32 cmd = 0;
    uint32 field_val = 0;
    uint16 step      = 0;
    uint16 step_mac  = 0;
    uint8  dp_id   = 0;
    uint8  txqm_id   = 0;
    uint16 index = 0;
    uint32 entry_num = 0;
    RefDivMcMacPulse_m pause_pulse;
    RefDivCpuMacPulse_m cpumac_pause_pulse;
    ds_t ds;
    uint16 mac_id = 0;
    uint16 shift = 0;
    sal_memset(&ds, 0, sizeof(ds));
    cmd = DRV_IOR(RefDivMcMacPulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &pause_pulse));
    step = RefDivMcMacPulse_cfgRefDivMcMac0Dp1SgmacPauseTimer0Pulse_f - RefDivMcMacPulse_cfgRefDivMcMac0Dp0SgmacPauseTimer0Pulse_f;
    step_mac = RefDivMcMacPulse_cfgRefDivMcMac1Dp0SgmacPauseTimer0Pulse_f - RefDivMcMacPulse_cfgRefDivMcMac0Dp0SgmacPauseTimer0Pulse_f;
    for (txqm_id = 0; txqm_id < MCHIP_CAP(SYS_CAP_TXQM_NUM_PER_DP); txqm_id ++)
    {
        for (dp_id = 0; dp_id < MCHIP_CAP(SYS_CAP_DP_MAX_NUM); dp_id ++)
        {
            /*156.25M, 1s/156.25M = time / ((Pulse + 1) >> 8)*/
            shift = step_mac * txqm_id + step * dp_id;
            SetRefDivMcMacPulse(V, cfgRefDivMcMac0Dp0SgmacPauseTimer0Pulse_f + shift, &pause_pulse, 0x4F00);
            SetRefDivMcMacPulse(V, cfgResetDivMcMac0Dp0SgmacPauseTimer0Pulse_f + shift, &pause_pulse, 0);
            SetRefDivMcMacPulse(V, cfgRefDivMcMac0Dp0SgmacPauseTimer1Pulse_f + shift, &pause_pulse, 0x9F00);/*for 2.5G*/
            SetRefDivMcMacPulse(V, cfgResetDivMcMac0Dp0SgmacPauseTimer1Pulse_f + shift, &pause_pulse, 0);
            SetRefDivMcMacPulse(V, cfgRefDivMcMac0Dp0SgmacPauseTimer2Pulse_f + shift, &pause_pulse, 0x2780);/*for 400G*/
            SetRefDivMcMacPulse(V, cfgResetDivMcMac0Dp0SgmacPauseTimer2Pulse_f + shift, &pause_pulse, 0);
            SetRefDivMcMacPulse(V, cfgRefDivMcMac0Dp0SgmacPauseTimer3Pulse_f + shift, &pause_pulse, 0x4F00);
            SetRefDivMcMacPulse(V, cfgResetDivMcMac0Dp0SgmacPauseTimer3Pulse_f + shift, &pause_pulse, 0);
        }
    }
    cmd = DRV_IOW(RefDivMcMacPulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &pause_pulse));

    cmd = DRV_IOR(RefDivCpuMacPulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &cpumac_pause_pulse));
    SetRefDivCpuMacPulse(V, cfgRefDivCpuMacPauseTimer0Pulse_f, &cpumac_pause_pulse, 0x4F00);
    SetRefDivCpuMacPulse(V, cfgResetDivCpuMacPauseTimer0Pulse_f, &cpumac_pause_pulse, 0);
    SetRefDivCpuMacPulse(V, cfgRefDivCpuMacPauseTimer1Pulse_f, &cpumac_pause_pulse, 0x9F00);/*for 2.5G*/
    SetRefDivCpuMacPulse(V, cfgResetDivCpuMacPauseTimer1Pulse_f, &cpumac_pause_pulse, 0);
    SetRefDivCpuMacPulse(V, cfgRefDivCpuMacPauseTimer2Pulse_f, &cpumac_pause_pulse, 0x2780);/*for 400G*/
    SetRefDivCpuMacPulse(V, cfgResetDivCpuMacPauseTimer2Pulse_f, &cpumac_pause_pulse, 0);
    SetRefDivCpuMacPulse(V, cfgRefDivCpuMacPauseTimer3Pulse_f, &cpumac_pause_pulse, 0x4F00);
    SetRefDivCpuMacPulse(V, cfgResetDivCpuMacPauseTimer3Pulse_f, &cpumac_pause_pulse, 0);
    cmd = DRV_IOW(RefDivCpuMacPulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &cpumac_pause_pulse));

    /*pause frame length could >=64*/
    cmd = DRV_IOW(NetRxCtl_t, NetRxCtl_cfgNormalAndPfc64Bytes_f);
    SYS_SET_FIELD_TBL_ALL_DP(lchip, cmd, field_val);

    CTC_ERROR_RETURN(_sys_tmm_port_flow_ctrl_cfg(lchip));

    /* TMG cpumac already inited, and not support oobfc */
    if (DRV_IS_TMG(lchip))
    {
        return CTC_E_NONE;
    }

    for (mac_id = SYS_CPU_MAC_ID_MIN; mac_id <= SYS_CPU_MAC_ID_MAX; mac_id++)
    {
        step = (Sgmac1RxPauseCfg_t - Sgmac0RxPauseCfg_t) * (mac_id - SYS_CPU_MAC_ID_MIN);
        cmd = DRV_IOR(Sgmac0RxPauseCfg_t + step, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
        SetSgmac0RxPauseCfg(V, cfgSgmac0RxNormPauseEn_f, &ds, 0);
        SetSgmac0RxPauseCfg(V, cfgSgmac0RxPfcPriorityEn_f, &ds, 0);
        cmd = DRV_IOW(Sgmac0RxPauseCfg_t + step, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
    }

    sys_usw_ftm_query_table_entry_num(lchip, OobFcPortMap_t, &entry_num);
    for (index = 0; index < entry_num; index++)
    {
        SetOobFcPortMap(V, data_f, &ds, 0x3F);
        cmd = DRV_IOW(OobFcPortMap_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds));
    }

    /*init for oobfc, oobfc clk < core_freq / 2, 1050/8=131.25m*/
    cmd = DRV_IOR(SupDskCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
    SetSupDskCfg(V, cfgClkOobFcTxDiv_f, &ds, 8);
    cmd = DRV_IOW(SupDskCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));

    /*Toggle the clock divider reset*/
    field_val = 1;
    cmd = DRV_IOW(SupDskCfg_t, SupDskCfg_cfgResetClkOobFcTxDiv_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));
    field_val = 0;
    cmd = DRV_IOW(SupDskCfg_t, SupDskCfg_cfgResetClkOobFcTxDiv_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));

    /*Cfg txClk output pin reset*/
    cmd = DRV_IOR(MacroMiscCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
    SetMacroMiscCtl(V, cfgEnClockOobFcOut_f, &ds, 1);
    cmd = DRV_IOW(MacroMiscCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
    return CTC_E_NONE;
}
int32
sys_tmm_port_set_oobfc_en(uint8 lchip, ctc_port_fc_prop_t *fc_prop)
{
    uint32 cmd                      = 0;
    uint32 field_val                = 0;
    uint16 lport                    = 0;
    uint8 tx_dir                    = 0;/*0:ingress request,1egerss request*/
    uint32 chan_en_bmp[8]           = {0};
    uint32 port_type                = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};
    DsIrmPortStallEn_m  irm_stall_en;
    sal_memset(&irm_stall_en, 0, sizeof(DsIrmPortStallEn_m));

    /*fc_prop->dir:tx per port w/ or w/o pri enable,rx global enable*/
    if (fc_prop->dir != CTC_EGRESS)
    {
        return CTC_E_INVALID_CONFIG;
    }

    lport = CTC_MAP_GPORT_TO_LPORT(fc_prop->gport);
    dmps_port_info.gport = fc_prop->gport;
    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_PORT_TYPE, (void *)&port_type));
    tx_dir = ((port_type != SYS_DMPS_NETWORK_PORT )&&(port_type != SYS_DMPS_CPUMAC_NETWORK_PORT ))? CTC_INGRESS : CTC_EGRESS;

    if(tx_dir == CTC_INGRESS)
    {
        /*Irm FC/PFC enable/disable*/
        cmd = DRV_IOR(DsIrmPortStallEn_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, lport, cmd, &irm_stall_en));
        if (fc_prop->is_pfc)
        {
            field_val = GetDsIrmPortStallEn(V, portPriEnVec_f, &irm_stall_en);
            (fc_prop->enable) ? CTC_BIT_SET(field_val, (fc_prop->priority_class)) : CTC_BIT_UNSET(field_val, (fc_prop->priority_class));
            SetDsIrmPortStallEn(V, portPriEnVec_f, &irm_stall_en, field_val);
            SetDsIrmPortStallEn(V, portOobFcEn_f, &irm_stall_en, field_val ? 1 : 0);
        }
        else
        {
            SetDsIrmPortStallEn(V, portOobFcEn_f, &irm_stall_en, fc_prop->enable ? 1 : 0);
        }

        cmd = DRV_IOW(DsIrmPortStallEn_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, lport, cmd, &irm_stall_en));
    }

    cmd = DRV_IOR(OobFcChanEn_t, OobFcChanEn_chanEn_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &chan_en_bmp));
    (fc_prop->enable) ? CTC_BMP_SET(chan_en_bmp, lport) : CTC_BMP_UNSET(chan_en_bmp, lport);
    cmd = DRV_IOW(OobFcChanEn_t, OobFcChanEn_chanEn_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &chan_en_bmp));

    return CTC_E_NONE;
}

int32
sys_tmm_port_get_oobfc_en(uint8 lchip, ctc_port_fc_prop_t *fc_prop)
{
    uint32 cmd                      = 0;
    uint32 field_val                = 0;
    uint16 lport                    = 0;
    uint8 tx_dir                    = 0;/*0:ingress request,1egerss request*/
    uint32 chan_en_bmp[8]           = {0};
    uint32 port_type                = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};
    DsIrmPortStallEn_m  irm_stall_en;
    sal_memset(&irm_stall_en, 0, sizeof(DsIrmPortStallEn_m));

    /*fc_prop->dir:tx per port w/ or w/o pri enable,rx global enable*/
    if (fc_prop->dir != CTC_EGRESS)
    {
        return CTC_E_INVALID_CONFIG;
    }

    lport = CTC_MAP_GPORT_TO_LPORT(fc_prop->gport);
    dmps_port_info.gport = fc_prop->gport;
    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_PORT_TYPE, (void *)&port_type));
    tx_dir = ((port_type != SYS_DMPS_NETWORK_PORT )&&(port_type != SYS_DMPS_CPUMAC_NETWORK_PORT ))? CTC_INGRESS : CTC_EGRESS;

    if(tx_dir == CTC_INGRESS)
    {
        /*Irm FC/PFC enable/disable*/
        cmd = DRV_IOR(DsIrmPortStallEn_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, lport, cmd, &irm_stall_en));
        if (fc_prop->is_pfc)
        {
            field_val = GetDsIrmPortStallEn(V, portPriEnVec_f, &irm_stall_en);
            fc_prop->enable = CTC_IS_BIT_SET(field_val, (fc_prop->priority_class));
        }
        else
        {
            field_val = GetDsIrmPortStallEn(V, portOobFcEn_f, &irm_stall_en);
            fc_prop->enable = field_val;
        }
    }
    else
    {
        cmd = DRV_IOR(OobFcChanEn_t, OobFcChanEn_chanEn_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &chan_en_bmp));
        fc_prop->enable = CTC_BMP_ISSET(chan_en_bmp, lport) == 0 ? 0 : 1;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_port_set_igs_flow_ctl_map(uint8 lchip, uint32 chan, ctc_port_fc_prop_t* fc_prop, uint8 is_recover, uint8* keep_enable)
{
    ds_t   ds;
    uint32 cmd = 0;
    uint32 field_val = 0;
    uint16 priority_class_bmp = fc_prop->priority_class_bmp;
    uint8  pfc_class = fc_prop->priority_class_bmp ? fc_prop->pfc_class : fc_prop->priority_class;
    uint8  disable_all = 0;
    uint8  loop = 0;
    uint8  step = 0;
    if(!fc_prop->is_pfc || CTC_EGRESS == fc_prop->dir || is_recover)
    {
        return CTC_E_NONE;
    }
    /*config pfc pri to queue map*/
    step = DsQMgrFlowCtlMap0_cos_1_sel_f - DsQMgrFlowCtlMap0_cos_0_sel_f;
    cmd = DRV_IOR(chan < MCHIP_CAP(SYS_CAP_PER_DP_CHANNEL_NUM) ? DsQMgrFlowCtlMap0_t : DsQMgrFlowCtlMap1_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, chan  % MCHIP_CAP(SYS_CAP_PER_DP_CHANNEL_NUM), cmd, &ds));
    disable_all = (CTC_IS_BIT_SET(priority_class_bmp, pfc_class) && GetDsQMgrFlowCtlMap0(V, cos_0_sel_f + step * pfc_class, &ds) == pfc_class) ? TRUE : FALSE;
    for (loop = 0; loop < SYS_PORT_PRIO_CLASS_NUM; loop++)
    {
        field_val = GetDsQMgrFlowCtlMap0(V, cos_0_sel_f + step * loop, &ds);
        if(fc_prop->enable)
        {
            if(CTC_IS_BIT_SET(priority_class_bmp, loop))
            {
                field_val = pfc_class;
            }
            else if(field_val == pfc_class || (loop == pfc_class && !priority_class_bmp))
            {
                field_val = loop;
            }
        }
        else
        {
            if((field_val == pfc_class && (CTC_IS_BIT_SET(priority_class_bmp, loop) || disable_all))
                || (!priority_class_bmp && (field_val == pfc_class || loop == pfc_class)))
            {
                field_val = loop;
            }
            else if(field_val == pfc_class && loop != pfc_class)
            {
                *keep_enable = TRUE;
            }
        }
        SetDsQMgrFlowCtlMap0(V, cos_0_sel_f + step * loop, &ds, field_val);
    }

    cmd = DRV_IOW(chan < MCHIP_CAP(SYS_CAP_PER_DP_CHANNEL_NUM) ? DsQMgrFlowCtlMap0_t : DsQMgrFlowCtlMap1_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, chan  % MCHIP_CAP(SYS_CAP_PER_DP_CHANNEL_NUM), cmd, &ds));

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_port_get_igs_flow_ctl_map(uint8 lchip, uint32 chan, ctc_port_fc_prop_t* fc_prop)
{
    ds_t   ds;
    uint32 cmd = 0;
    uint8  loop = 0;
    uint8  step = 0;

    if(!fc_prop->is_pfc || !fc_prop->enable || CTC_EGRESS == fc_prop->dir)
    {
        return CTC_E_NONE;
    }

    /*config pfc pri to queue map*/
    step = DsQMgrFlowCtlMap0_cos_1_sel_f - DsQMgrFlowCtlMap0_cos_0_sel_f;
    cmd = DRV_IOR(chan < MCHIP_CAP(SYS_CAP_PER_DP_CHANNEL_NUM) ? DsQMgrFlowCtlMap0_t : DsQMgrFlowCtlMap1_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, chan  % MCHIP_CAP(SYS_CAP_PER_DP_CHANNEL_NUM), cmd, &ds));
    fc_prop->pfc_class = GetDsQMgrFlowCtlMap0(V, cos_0_sel_f + step * fc_prop->priority_class, &ds);

    for (loop = 0; loop < SYS_PORT_PRIO_CLASS_NUM; loop++)
    {
        if(fc_prop->pfc_class == GetDsQMgrFlowCtlMap0(V, cos_0_sel_f + step * loop, &ds))
        {
            CTC_BIT_SET(fc_prop->priority_class_bmp, loop);
        }
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_port_set_obmfc_en2(uint8 lchip, uint32 mac_id, ctc_port_fc_prop_t *fc_prop)
{
    uint32 cmd = 0;
    uint32 rx_pause_type[5] = {0};
    uint32 rx_pause_req_en[5] = {0};
    uint32 field_val = 0;
    uint16 step = 0;
    uint8 dp_id = mac_id / MCHIP_CAP(SYS_CAP_MAC_NUM_PER_DP);
    uint8 lmac_id = mac_id % MCHIP_CAP(SYS_CAP_MAC_NUM_PER_DP);
    uint8 txqm_id = mac_id / MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM);
    NetRxPauseReqCtl_m net_rx_pause_ctl;
    NetRxPausePriRemap_m net_rx_pause_pri_remap;
    Sgmac0TxPauseCfg_m tx_pause_cfg;
    if(fc_prop->dir != CTC_EGRESS || mac_id >= SYS_CPU_MAC_ID_MIN)
    {
        return CTC_E_INVALID_CONFIG;
    }

    cmd = DRV_IOR(NetRxPausePriRemap_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, mac_id, cmd, &net_rx_pause_pri_remap));
    SetNetRxPausePriRemap(V, prio_f, &net_rx_pause_pri_remap, fc_prop->is_pfc && fc_prop->enable ? fc_prop->priority_class_bmp : 0);
    cmd = DRV_IOW(NetRxPausePriRemap_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, mac_id, cmd, &net_rx_pause_pri_remap));

    if(fc_prop->enable)
    {
        /*change pause type*/
        cmd = DRV_IOR(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, dp_id, cmd, &net_rx_pause_ctl));
        GetNetRxPauseReqCtl(A, netRxPauseType_f, &net_rx_pause_ctl, rx_pause_type);
        if (fc_prop->is_pfc && fc_prop->enable)
        {
            CTC_BIT_SET(rx_pause_type[lmac_id >> 5], (lmac_id&0x1F));
        }
        else if ( !fc_prop->is_pfc && fc_prop->enable)
        {
            CTC_BIT_UNSET(rx_pause_type[lmac_id >> 5], (lmac_id&0x1F));
        }
        SetNetRxPauseReqCtl(A, netRxPauseType_f, &net_rx_pause_ctl, rx_pause_type);
        cmd = DRV_IOW(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, dp_id, cmd, &net_rx_pause_ctl));

        field_val = fc_prop->is_pfc ? 1 : 0;
        step = (Sgmac1TxPauseCfg_t - Sgmac0TxPauseCfg_t) * (mac_id % MCHIP_CAP(SYS_CAP_STATS_XQMAC_PORT_NUM));
        cmd = DRV_IOR(Sgmac0TxPauseCfg_t + step, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, mac_id / MCHIP_CAP(SYS_CAP_STATS_XQMAC_PORT_NUM), cmd, &tx_pause_cfg));
        SetSgmac0TxPauseCfg(V, cfgSgmac0TxPauseType_f, &tx_pause_cfg, field_val);
        cmd = DRV_IOW(Sgmac0TxPauseCfg_t + step, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, mac_id / MCHIP_CAP(SYS_CAP_STATS_XQMAC_PORT_NUM), cmd, &tx_pause_cfg));
    }

    step = (NetRxPauseReqCtl_netRxPauseReqEn1_f - NetRxPauseReqCtl_netRxPauseReqEn0_f) * (lmac_id / MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM));
    cmd = DRV_IOR(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, dp_id, cmd, &net_rx_pause_ctl));
    GetNetRxPauseReqCtl(A, netRxPauseReqEn0_f + step, &net_rx_pause_ctl, rx_pause_req_en);
    fc_prop->enable ? CTC_BMP_SET(rx_pause_req_en, lmac_id % MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM))
                    : CTC_BMP_UNSET(rx_pause_req_en, lmac_id % MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM));
    SetNetRxPauseReqCtl(A, netRxPauseReqEn0_f + step, &net_rx_pause_ctl, rx_pause_req_en);
    cmd = DRV_IOW(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, dp_id, cmd, &net_rx_pause_ctl));

    /*diable:force mac sending xon pause*/
    if (!fc_prop->enable)
    {
        NetRxNetPriLog_m rx_pri_log;
        NetRxForcePauseReq_m force_pause_req;
        uint16 dpport = txqm_id * MCHIP_CAP(SYS_CAP_DPPORT_NUM_PER_TXQM) + mac_id % MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM);

        cmd = DRV_IOR(NetRxNetPriLog_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, dpport, cmd, &rx_pri_log));
        SetNetRxNetPriLog(V, data_f, &rx_pri_log, 0);
        cmd = DRV_IOW(NetRxNetPriLog_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, dpport, cmd, &rx_pri_log));

        cmd = DRV_IOR(NetRxForcePauseReq_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, dp_id, cmd, &force_pause_req));
        SetNetRxForcePauseReq(V, cfgForcePauseReqPortId_f, &force_pause_req, dpport % (MCHIP_CAP(SYS_CAP_TXQM_NUM_PER_DP) * MCHIP_CAP(SYS_CAP_DPPORT_NUM_PER_TXQM)));
        cmd = DRV_IOW(NetRxForcePauseReq_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, dp_id, cmd, &force_pause_req));
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_port_get_obmfc_en2(uint8 lchip, uint32 mac_id, ctc_port_fc_prop_t *fc_prop)
{
    uint32 cmd = 0;
    uint32 rx_pause_req_en[5] = {0};
    uint8 step = 0;
    uint8 lmac_id = mac_id % MCHIP_CAP(SYS_CAP_MAC_NUM_PER_DP);
    NetRxPauseReqCtl_m net_rx_pause_ctl;
    NetRxPausePriRemap_m net_rx_pause_pri_remap;
    if(fc_prop->dir != CTC_EGRESS || mac_id >= SYS_CPU_MAC_ID_MIN)
    {
        return CTC_E_INVALID_CONFIG;
    }

    step = (NetRxPauseReqCtl_netRxPauseReqEn1_f - NetRxPauseReqCtl_netRxPauseReqEn0_f) * (lmac_id / MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM));
    cmd = DRV_IOR(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, mac_id / MCHIP_CAP(SYS_CAP_MAC_NUM_PER_DP), cmd, &net_rx_pause_ctl));
    GetNetRxPauseReqCtl(A, netRxPauseReqEn0_f + step, &net_rx_pause_ctl, rx_pause_req_en);
    fc_prop->enable = CTC_BMP_ISSET(rx_pause_req_en, lmac_id % MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM)) ? 1 : 0;

    cmd = DRV_IOR(NetRxPausePriRemap_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, mac_id, cmd, &net_rx_pause_pri_remap));
    fc_prop->priority_class_bmp = GetNetRxPausePriRemap(V, prio_f, &net_rx_pause_pri_remap);
    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_port_set_obmfc_en(uint8 lchip, uint32 mac_id, ctc_port_fc_prop_t *fc_prop)
{
    uint32 cmd = 0;
    uint32 rx_pause_type[5] = {0};
    uint32 rx_pause_req_en[5] = {0};
    uint32 field_val = 0;
    uint16 step = 0;
    uint8 dp_id = mac_id / MCHIP_CAP(SYS_CAP_MAC_NUM_PER_DP);
    uint8 lmac_id = mac_id % MCHIP_CAP(SYS_CAP_MAC_NUM_PER_DP);
    NetRxPauseReqCtl_m net_rx_pause_ctl;
    NetRxPausePriRemap_m net_rx_pause_pri_remap;
    if(fc_prop->dir != CTC_EGRESS || mac_id >= SYS_CPU_MAC_ID_MIN)
    {
        return CTC_E_INVALID_CONFIG;
    }

    cmd = DRV_IOR(NetRxPausePriRemap_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, mac_id, cmd, &net_rx_pause_pri_remap));
    SetNetRxPausePriRemap(V, prio_f, &net_rx_pause_pri_remap, fc_prop->is_pfc && fc_prop->enable ? fc_prop->priority_class_bmp : 0);
    cmd = DRV_IOW(NetRxPausePriRemap_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, mac_id, cmd, &net_rx_pause_pri_remap));

    if(fc_prop->enable)
    {
        /*change pause type*/
        cmd = DRV_IOR(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, dp_id, cmd, &net_rx_pause_ctl));
        GetNetRxPauseReqCtl(A, netRxPauseType_f, &net_rx_pause_ctl, rx_pause_type);
        if (fc_prop->is_pfc && fc_prop->enable)
        {
            CTC_BIT_SET(rx_pause_type[lmac_id >> 5], (lmac_id&0x1F));
        }
        else if ( !fc_prop->is_pfc && fc_prop->enable)
        {
            CTC_BIT_UNSET(rx_pause_type[lmac_id >> 5], (lmac_id&0x1F));
        }
        SetNetRxPauseReqCtl(A, netRxPauseType_f, &net_rx_pause_ctl, rx_pause_type);
        cmd = DRV_IOW(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, dp_id, cmd, &net_rx_pause_ctl));

        field_val = fc_prop->is_pfc ? 1 : 0;
        step = (McMacPauseTxCtl_mcMacPauseTxCfg_1_cfgMcMacTxPauseType_f - McMacPauseTxCtl_mcMacPauseTxCfg_0_cfgMcMacTxPauseType_f)* (mac_id % MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM));
        cmd = DRV_IOW(McMacPauseTxCtl_t, McMacPauseTxCtl_mcMacPauseTxCfg_0_cfgMcMacTxPauseType_f + step);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, mac_id / MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM), cmd, &field_val));
    }

    cmd = DRV_IOR(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, dp_id, cmd, &net_rx_pause_ctl));
    GetNetRxPauseReqCtl(A, netRxPauseReqEn_f, &net_rx_pause_ctl, rx_pause_req_en);
    fc_prop->enable ? CTC_BMP_SET(rx_pause_req_en, mac_id % MCHIP_CAP(SYS_CAP_MAC_NUM_PER_DP))
                    : CTC_BMP_UNSET(rx_pause_req_en, mac_id % MCHIP_CAP(SYS_CAP_MAC_NUM_PER_DP));
    SetNetRxPauseReqCtl(A, netRxPauseReqEn_f, &net_rx_pause_ctl, rx_pause_req_en);
    cmd = DRV_IOW(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, dp_id, cmd, &net_rx_pause_ctl));

    /*diable:force mac sending xon pause*/
    if (!fc_prop->enable)
    {
        field_val = 0;
        cmd = DRV_IOW(NetRxNetPriLog_t, NetRxNetPriLog_data_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, mac_id, cmd, &field_val));

        field_val = mac_id % MCHIP_CAP(SYS_CAP_MAC_NUM_PER_DP);
        cmd = DRV_IOW(NetRxForcePauseReq_t, NetRxForcePauseReq_cfgForcePauseReqPortId_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, dp_id, cmd, &field_val));

        field_val = 0;
        step = (McMacPauseTxCtl_mcMacPauseTxCfg_1_dbgMcMacTxPauseCurStatus_f - McMacPauseTxCtl_mcMacPauseTxCfg_0_dbgMcMacTxPauseCurStatus_f)
                     * (mac_id % MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM));
        cmd = DRV_IOW(McMacPauseTxCtl_t, McMacPauseTxCtl_mcMacPauseTxCfg_0_dbgMcMacTxPauseCurStatus_f + step);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, dp_id, cmd, &field_val));
        cmd = DRV_IOW(McMacPauseTxCtl_t, McMacPauseTxCtl_mcMacPauseTxCfg_0_dbgMcMacTxPauseLogStatus_f + step);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, dp_id, cmd, &field_val));
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_port_get_obmfc_en(uint8 lchip, uint32 mac_id, ctc_port_fc_prop_t *fc_prop)
{
    uint32 cmd = 0;
    uint32 rx_pause_req_en[5] = {0};
    NetRxPauseReqCtl_m net_rx_pause_ctl;
    NetRxPausePriRemap_m net_rx_pause_pri_remap;
    if(fc_prop->dir != CTC_EGRESS || mac_id >= SYS_CPU_MAC_ID_MIN)
    {
        return CTC_E_INVALID_CONFIG;
    }

    cmd = DRV_IOR(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, mac_id / MCHIP_CAP(SYS_CAP_MAC_NUM_PER_DP), cmd, &net_rx_pause_ctl));
    GetNetRxPauseReqCtl(A, netRxPauseReqEn_f, &net_rx_pause_ctl, rx_pause_req_en);
    fc_prop->enable = CTC_BMP_ISSET(rx_pause_req_en, mac_id % MCHIP_CAP(SYS_CAP_MAC_NUM_PER_DP)) ? 1 : 0;

    cmd = DRV_IOR(NetRxPausePriRemap_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, mac_id, cmd, &net_rx_pause_pri_remap));
    fc_prop->priority_class_bmp = GetNetRxPausePriRemap(V, prio_f, &net_rx_pause_pri_remap);
    return CTC_E_NONE;
}

int32
sys_tmm_port_set_flow_ctl_en(uint8 lchip, void* p_fc_prop, uint8 is_recover)
{
    uint8 old_is_pfc = 0;
    uint8 old_is_fc = 0;
    uint8 dp_id = 0;
    uint8 lmac_id = 0;
    uint32 chan_id = 0;/*egress chan*/
    uint32 chan_id1 = 0;/*ingress chan*/
    uint8 tmp_chan = 0; 
    uint32 mac_id = 0;
    uint16 step = 0;
    uint32 rx_pause_type[5] = {0};
    uint32 rx_pause_req_en[5] = {0};
    uint32 cmd = 0;
    uint32 field_val = 0;
    uint32 index = 0;
    uint8 igs_pfc_en = 0;
    uint8 egs_pfc_en = 0;
    uint8 normal_fc_en = 0;
    NetRxPauseReqCtl_m net_rx_pause_ctl;
    McMacPauseRxCtl_m mac_rx_pause_ctl;
    McMacPauseTxCtl_m mac_tx_pause_ctl;
    DsIrmPortStallEn_m  irm_stall_en;
    DsNetRxPauseStats_m netrx_pause_stats;
    NetRxPausePriRemap_m net_rx_pause_pri_remap;
    uint32 cpumac_pause_type = 0;
    ds_t   ds;
    ctc_port_fc_prop_t *fc_prop = (ctc_port_fc_prop_t *)p_fc_prop;
    sys_usw_dmps_port_info_t dmps_port_info = {0};
    uint8 pfc_class = 0;
    uint8 keep_enable = FALSE;

    sal_memset(&ds, 0, sizeof(ds));
    sal_memset(&net_rx_pause_ctl, 0, sizeof(NetRxPauseReqCtl_m));
    sal_memset(&mac_rx_pause_ctl, 0, sizeof(McMacPauseRxCtl_m));
    sal_memset(&mac_tx_pause_ctl, 0, sizeof(McMacPauseTxCtl_m));
    sal_memset(&irm_stall_en, 0, sizeof(DsIrmPortStallEn_m));

    SYS_PORT_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_PORT_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Set gport:0x%04X \n", fc_prop->gport);

    if (fc_prop->priority_class_bmp)
    {
        if ((fc_prop->dir != CTC_INGRESS && fc_prop->type == CTC_PORT_FC_TYPE_NORMAL)
            || (fc_prop->dir != CTC_EGRESS && fc_prop->type == CTC_PORT_FC_TYPE_OBM)
            || (fc_prop->is_oobfc || fc_prop->type == CTC_PORT_FC_TYPE_OOB) || fc_prop->dir >= CTC_BOTH_DIRECTION 
            || !fc_prop->is_pfc || (fc_prop->priority_class_bmp >> SYS_PORT_PRIO_CLASS_NUM) > 0)
        {
            return CTC_E_INVALID_CONFIG;
        }
        pfc_class = fc_prop->pfc_class;
    }
    else
    {
        pfc_class = fc_prop->priority_class;
    }
    CTC_MAX_VALUE_CHECK(pfc_class, SYS_PORT_PRIO_CLASS_NUM - 1);

    if(fc_prop->is_oobfc || CTC_PORT_FC_TYPE_OOB == fc_prop->type)
    {
        return DRV_IS_TMG(lchip) ? CTC_E_NOT_SUPPORT : sys_tmm_port_set_oobfc_en(lchip, fc_prop);
    }
    dmps_port_info.gport = fc_prop->gport;
    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_MAC_ID, (void *)&mac_id));
    if (0xff == mac_id)
    {
        return CTC_E_INVALID_CONFIG;
    }

    /*for xpipe
     *pfc ingress : back pressure to low priority chan
     *pfc egress  : CTC_PORT_XPIPE_TYPE_1/CTC_PORT_XPIPE_TYPE_3 triggered by high priority chan, else low priority chan.
     */
    CTC_ERROR_RETURN(sys_usw_port_get_property(lchip, fc_prop->gport, CTC_PORT_PROP_XPIPE_EN, &field_val)); 
    if(field_val && !CTC_IS_MCHAN_PORT(fc_prop->gport))
    {
        CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_GET_PMAC_CHAN_ID, &chan_id));          /*high priority chan*/
        CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &chan_id1));  /*low priority chan*/
        chan_id = (field_val == CTC_PORT_XPIPE_TYPE_1 || field_val == CTC_PORT_XPIPE_TYPE_3) ? chan_id : chan_id1; /*CTC_PORT_XPIPE_TYPE_2 low, else high*/
    }
    else
    {
        CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &chan_id));
        chan_id1 = chan_id; /*low*/
    }
    if (SYS_COMMON_USELESS_CHANNEL == chan_id1 || SYS_COMMON_USELESS_CHANNEL == chan_id)
    {
        return CTC_E_INVALID_CONFIG;
    }
    tmp_chan = chan_id % MCHIP_CAP(SYS_CAP_PER_DP_CHANNEL_NUM);
    
    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_SPEED_MODE, (void *)&field_val));
    if (DRV_IS_TMM(lchip) && (SYS_GET_CHIP_VERSION == SYS_CHIP_SUB_VERSION_A) && field_val <= CTC_PORT_SPEED_2G5)
    {
        return CTC_E_NOT_SUPPORT;
    }

    CTC_ERROR_RETURN(_sys_tmm_port_set_igs_flow_ctl_map(lchip, chan_id1, fc_prop, is_recover, &keep_enable));
    if(keep_enable)
    {
        return CTC_E_NONE;
    }

    if (mac_id < SYS_CPU_MAC_ID_MIN)
    {
        uint8 rx_req_en = 0;
        /*FC/PFC enable/disable*/
        if (DRV_IS_TMG(lchip))
        {
            step = (Sgmac1RxPauseCfg_t - Sgmac0RxPauseCfg_t) * (mac_id % MCHIP_CAP(SYS_CAP_STATS_XQMAC_PORT_NUM));
            cmd = DRV_IOR(Sgmac0RxPauseCfg_t + step, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, mac_id / MCHIP_CAP(SYS_CAP_STATS_XQMAC_PORT_NUM), cmd, &ds));
            igs_pfc_en = GetSgmac0RxPauseCfg(V, cfgSgmac0RxPfcPriorityEn_f, &ds);

            cmd = DRV_IOR(DsIrmPortStallEn_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, chan_id, cmd, &irm_stall_en));
            egs_pfc_en = GetDsIrmPortStallEn(V, portPriEnVec_f, &irm_stall_en);
            normal_fc_en = GetDsIrmPortStallEn(V, portFcEn_f, &irm_stall_en);

            step = (NetRxPauseReqCtl_netRxPauseReqEn1_f - NetRxPauseReqCtl_netRxPauseReqEn0_f) * (mac_id % MCHIP_CAP(SYS_CAP_MAC_NUM_PER_DP) / MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM));
            cmd = DRV_IOR(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, mac_id / MCHIP_CAP(SYS_CAP_MAC_NUM_PER_DP), cmd, &net_rx_pause_ctl));
            GetNetRxPauseReqCtl(A, netRxPauseType_f, &net_rx_pause_ctl, rx_pause_type);
            GetNetRxPauseReqCtl(A, netRxPauseReqEn0_f + step, &net_rx_pause_ctl, rx_pause_req_en);

            rx_req_en = CTC_BMP_ISSET(rx_pause_req_en, mac_id % MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM));
        }
        else
        {
            step = (McMacPauseRxCtl_mcMacPauseRxCfg_1_cfgMcMacRxPfcPauseEn_f - McMacPauseRxCtl_mcMacPauseRxCfg_0_cfgMcMacRxPfcPauseEn_f)
                    * (mac_id % MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM));
            cmd = DRV_IOR(McMacPauseRxCtl_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, mac_id / MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM), cmd, &mac_rx_pause_ctl));
            igs_pfc_en = GetMcMacPauseRxCtl(V, mcMacPauseRxCfg_0_cfgMcMacRxPfcPriorityEn_f + step, &mac_rx_pause_ctl);

            cmd = DRV_IOR(DsIrmPortStallEn_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, chan_id, cmd, &irm_stall_en));
            egs_pfc_en = GetDsIrmPortStallEn(V, portPriEnVec_f, &irm_stall_en);
            normal_fc_en = GetDsIrmPortStallEn(V, portFcEn_f, &irm_stall_en);

            cmd = DRV_IOR(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, mac_id / MCHIP_CAP(SYS_CAP_MAC_NUM_PER_DP), cmd, &net_rx_pause_ctl));
            GetNetRxPauseReqCtl(A, netRxPauseType_f, &net_rx_pause_ctl, rx_pause_type);
            GetNetRxPauseReqCtl(A, netRxPauseReqEn_f, &net_rx_pause_ctl, rx_pause_req_en);

            rx_req_en = CTC_BMP_ISSET(rx_pause_req_en, mac_id % MCHIP_CAP(SYS_CAP_MAC_NUM_PER_DP));
        }
        cmd = DRV_IOR(NetRxPausePriRemap_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, mac_id, cmd, &net_rx_pause_pri_remap));
        field_val = GetNetRxPausePriRemap(V, prio_f, &net_rx_pause_pri_remap);
        if((fc_prop->is_pfc && rx_req_en && !field_val)
        || (!fc_prop->is_pfc && rx_req_en && field_val)
        || (CTC_PORT_FC_TYPE_OBM == fc_prop->type && !fc_prop->is_pfc && (igs_pfc_en || egs_pfc_en))
        || (CTC_PORT_FC_TYPE_OBM == fc_prop->type && fc_prop->is_pfc && normal_fc_en))
        {
            return CTC_E_INVALID_CONFIG;
        }
    }
    if(CTC_PORT_FC_TYPE_OBM == fc_prop->type)
    {
        return DRV_IS_TMG(lchip) ? _sys_tmm_port_set_obmfc_en2(lchip, mac_id, fc_prop)
                                 : _sys_tmm_port_set_obmfc_en(lchip, mac_id, fc_prop);
    }

    SYS_PORT_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "ingress chan_id:%d, mac_id:%d\n", chan_id1, mac_id);
    SYS_PORT_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "egress chan_id:%d, mac_id:%d\n", chan_id, mac_id);
    if (mac_id >= SYS_CPU_MAC_ID_MIN && mac_id <= SYS_CPU_MAC_ID_MAX)
    {
        dp_id = (mac_id - SYS_CPU_MAC_ID_MIN) / MCHIP_CAP(SYS_CAP_CPUMAC_NUM_PER_DP);
        if ((CTC_INGRESS == fc_prop->dir) || (CTC_BOTH_DIRECTION == fc_prop->dir))
        {
            /*FC/PFC enable/disable*/
            step = (Sgmac1RxPauseCfg_t - Sgmac0RxPauseCfg_t) * (mac_id - SYS_CPU_MAC_ID_MIN);
            index = DRV_IS_TMG(lchip) ? (mac_id / MCHIP_CAP(SYS_CAP_STATS_XQMAC_PORT_NUM)) : 0;
            cmd = DRV_IOR(Sgmac0RxPauseCfg_t + step, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds));

            old_is_pfc = GetSgmac0RxPauseCfg(V, cfgSgmac0RxPfcPauseEn_f, &ds);
            old_is_fc = GetSgmac0RxPauseCfg(V, cfgSgmac0RxNormPauseEn_f, &ds);

            if(!fc_prop->enable && ((fc_prop->is_pfc && old_is_fc) || (!fc_prop->is_pfc && old_is_pfc) || (!old_is_pfc && !old_is_fc)))
            {
                return CTC_E_NONE;
            }

            if (fc_prop->is_pfc)
            {
                SetSgmac0RxPauseCfg(V, cfgSgmac0RxPfcPauseEn_f, &ds, 1);
                field_val = GetSgmac0RxPauseCfg(V, cfgSgmac0RxPfcPriorityEn_f, &ds);
                (fc_prop->enable) ? CTC_BIT_SET(field_val, pfc_class) : CTC_BIT_UNSET(field_val, pfc_class);
                SetSgmac0RxPauseCfg(V, cfgSgmac0RxPfcPriorityEn_f , &ds, field_val);
                SetSgmac0RxPauseCfg(V, cfgSgmac0RxNormPauseEn_f, &ds, 0);
            }
            else
            {
                field_val = (fc_prop->enable) ? 1 : 0;
                SetSgmac0RxPauseCfg(V, cfgSgmac0RxNormPauseEn_f, &ds, field_val);
                SetSgmac0RxPauseCfg(V, cfgSgmac0RxPfcPauseEn_f, &ds, 0);
                SetSgmac0RxPauseCfg(V, cfgSgmac0RxPfcPriorityEn_f , &ds, 0);
            }
            cmd = DRV_IOW(Sgmac0RxPauseCfg_t + step, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds));

            if((old_is_pfc && !fc_prop->is_pfc) || fc_prop->is_pfc)
            {
                /*config group flowctl enable*/
                if (MCHIP_QOS(lchip)->qos_sch_update_fc_group)
                {
                    CTC_ERROR_RETURN(MCHIP_QOS(lchip)->qos_sch_update_fc_group(lchip, chan_id1, 0, 0, (field_val && fc_prop->is_pfc) ? 1 : 0));
                }
            }

            if(old_is_pfc && !fc_prop->is_pfc)
            {
                field_val = 0;
                cmd = DRV_IOW(DsQMgrFlowCtlState_t, DsQMgrFlowCtlState_stallValid_f);
                CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, chan_id1, cmd, &field_val));
            }
        }

        /*pfc/fc enable/disable and dynamic switch*/
        if ((CTC_EGRESS == fc_prop->dir) || (CTC_BOTH_DIRECTION == fc_prop->dir))
        {
            /*get old Irm FC/PFC enable/disable*/
            cmd = DRV_IOR(DsIrmPortStallEn_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, chan_id, cmd, &irm_stall_en));
            old_is_pfc = GetDsIrmPortStallEn(V, portPriEnVec_f, &irm_stall_en);
            old_is_fc = GetDsIrmPortStallEn(V, portFcEn_f, &irm_stall_en) && !old_is_pfc;
            if(!fc_prop->enable && ((fc_prop->is_pfc && old_is_fc) || (!fc_prop->is_pfc && old_is_pfc) || (!old_is_pfc && !old_is_fc)))
            {
                return CTC_E_NONE;
            }
            if (fc_prop->enable && ((fc_prop->is_pfc && old_is_fc) || (!fc_prop->is_pfc && old_is_pfc)))
            {
                /*switch_1 :config netrx: do not response to IRM request*/
                cmd = DRV_IOR(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, dp_id, cmd, &net_rx_pause_ctl));
                GetNetRxPauseReqCtl(A, bsPauseMaskBmp_f, &net_rx_pause_ctl, rx_pause_type);
                CTC_BIT_SET(rx_pause_type[tmp_chan >> 5], (tmp_chan&0x1F));
                SetNetRxPauseReqCtl(A, bsPauseMaskBmp_f, &net_rx_pause_ctl, rx_pause_type);
                cmd = DRV_IOW(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, dp_id, cmd, &net_rx_pause_ctl));
            }

            if (!fc_prop->enable || (fc_prop->is_pfc && old_is_fc) || (!fc_prop->is_pfc && old_is_pfc))
            {
                if (!fc_prop->enable)
                {
                    /*diable_1:config IRM*/
                    if (fc_prop->is_pfc)
                    {
                        field_val = old_is_pfc & (~(1 << fc_prop->priority_class));
                        cmd = DRV_IOW(DsIrmPortStallEn_t, DsIrmPortStallEn_portPriEnVec_f);
                        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, chan_id, cmd, &field_val));
                    }
                    if((old_is_pfc && fc_prop->is_pfc && !field_val) || 
                        (old_is_fc && !fc_prop->is_pfc))
                    {
                        field_val = 0;
                        cmd = DRV_IOW(DsIrmPortStallEn_t, DsIrmPortStallEn_portFcEn_f);
                        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, chan_id, cmd, &field_val));
                    }
                }
                /*switch_2/diable_2:clear port xoff status*/
                field_val = (mac_id - SYS_CPU_MAC_ID_MIN) + (MCHIP_CAP(SYS_CAP_DPPORT_NUM_PER_TXQM) * MCHIP_CAP(SYS_CAP_TXQM_NUM_PER_DP) * MCHIP_CAP(SYS_CAP_DP_MAX_NUM));
                sal_memset(&netrx_pause_stats, 0, sizeof(DsNetRxPauseStats_m));
                SetDsNetRxPauseStats(V,pauseStatsWrEn_f,&netrx_pause_stats,1);
                SetDsNetRxPauseStats(V,pauseStatsPort_f,&netrx_pause_stats,field_val);
                SetDsNetRxPauseStats(V,pauseStatsStallVec_f,&netrx_pause_stats,(!fc_prop->enable ? (fc_prop->is_pfc ? 1 << fc_prop->priority_class : 0xff) : (fc_prop->is_pfc ? 0x1 : 0xff)));
                cmd = DRV_IOW(DsNetRxPauseStats_t,DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, dp_id, cmd, &netrx_pause_stats));

                /*switch_3/diable_3:force mac sending xon pause*/
                cmd = DRV_IOW(NetRxForcePauseReq_t, NetRxForcePauseReq_cfgForcePauseReqPortId_f);
                CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, dp_id, cmd, &field_val));

                if (!fc_prop->enable)
                {
                    return CTC_E_NONE;
                }
            }

            field_val = fc_prop->is_pfc ? (old_is_pfc | 1 << fc_prop->priority_class) : 0;
            cmd = DRV_IOW(DsIrmPortStallEn_t, DsIrmPortStallEn_portPriEnVec_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, chan_id, cmd, &field_val));
            field_val = fc_prop->enable ? 1 : 0;
            cmd = DRV_IOW(DsIrmPortStallEn_t, DsIrmPortStallEn_portFcEn_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, chan_id, cmd, &field_val));
            if(!((fc_prop->is_pfc && old_is_pfc) || (!fc_prop->is_pfc && old_is_fc)))
            {
            /*switch_4/enable_1:change pause type*/
            cmd = DRV_IOR(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, dp_id, cmd, &net_rx_pause_ctl));
            cpumac_pause_type = GetNetRxPauseReqCtl(V, cfgCpuMacPauseType_f, &net_rx_pause_ctl);

            if (fc_prop->is_pfc && fc_prop->enable)
            {
                CTC_BIT_SET(cpumac_pause_type, ((mac_id - SYS_CPU_MAC_ID_MIN)&0x1));
            }
            else if ( !fc_prop->is_pfc && fc_prop->enable)
            {
                CTC_BIT_UNSET(cpumac_pause_type,((mac_id - SYS_CPU_MAC_ID_MIN)&0x1));
            }

            SetNetRxPauseReqCtl(V, cfgCpuMacPauseType_f, &net_rx_pause_ctl, cpumac_pause_type);
            cmd = DRV_IOW(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, dp_id, cmd, &net_rx_pause_ctl));

                step = (Sgmac1TxPauseCfg_t - Sgmac0TxPauseCfg_t) * (mac_id - SYS_CPU_MAC_ID_MIN);
                index = DRV_IS_TMG(lchip) ? (mac_id / MCHIP_CAP(SYS_CAP_STATS_XQMAC_PORT_NUM)) : 0;
                field_val = fc_prop->is_pfc ? 1 : 0;
                cmd = DRV_IOR(Sgmac0TxPauseCfg_t + step, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds));
                SetSgmac0TxPauseCfg(V, cfgSgmac0TxPauseType_f, &ds, field_val);
                cmd = DRV_IOW(Sgmac0TxPauseCfg_t + step, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds));
            }
            if (fc_prop->enable && ((fc_prop->is_pfc && old_is_fc) || (!fc_prop->is_pfc && old_is_pfc)))
            {
                /*switch_5:config netrx: response to IRM request*/
                cmd = DRV_IOR(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, dp_id, cmd, &net_rx_pause_ctl));
                GetNetRxPauseReqCtl(A, bsPauseMaskBmp_f, &net_rx_pause_ctl, rx_pause_type);
                CTC_BIT_UNSET(rx_pause_type[tmp_chan >> 5], (tmp_chan&0x1F));
                SetNetRxPauseReqCtl(A, bsPauseMaskBmp_f, &net_rx_pause_ctl, rx_pause_type);
                cmd = DRV_IOW(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, dp_id, cmd, &net_rx_pause_ctl));
            }
        }
    }
    else
    {

        dp_id = mac_id / MCHIP_CAP(SYS_CAP_MAC_NUM_PER_DP);
        lmac_id = mac_id % MCHIP_CAP(SYS_CAP_MAC_NUM_PER_DP);
        if (DRV_IS_TMG(lchip))
        {
            lmac_id = lmac_id / MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM) * MCHIP_CAP(SYS_CAP_DPPORT_NUM_PER_TXQM) + lmac_id % MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM);
        }

        if ((CTC_INGRESS == fc_prop->dir) || (CTC_BOTH_DIRECTION == fc_prop->dir))
        {
            if (DRV_IS_TMG(lchip))
            {
                step = (Sgmac1RxPauseCfg_t - Sgmac0RxPauseCfg_t) * (mac_id % MCHIP_CAP(SYS_CAP_STATS_XQMAC_PORT_NUM));
                index = mac_id / MCHIP_CAP(SYS_CAP_STATS_XQMAC_PORT_NUM);
                cmd = DRV_IOR(Sgmac0RxPauseCfg_t + step, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds));

                old_is_pfc = GetSgmac0RxPauseCfg(V, cfgSgmac0RxPfcPauseEn_f + step, &ds);
                old_is_fc = GetSgmac0RxPauseCfg(V, cfgSgmac0RxNormPauseEn_f + step, &ds);

                if (!fc_prop->enable && ((fc_prop->is_pfc && old_is_fc) || (!fc_prop->is_pfc && old_is_pfc) || (!old_is_pfc && !old_is_fc)))
                {
                    return CTC_E_NONE;
                }

                if (fc_prop->is_pfc)
                {
                    SetSgmac0RxPauseCfg(V, cfgSgmac0RxPfcPauseEn_f, &ds, 1);
                    field_val = GetSgmac0RxPauseCfg(V, cfgSgmac0RxPfcPriorityEn_f, &ds);
                    fc_prop->enable ? CTC_BIT_SET(field_val, pfc_class): CTC_BIT_UNSET(field_val, pfc_class);
                    SetSgmac0RxPauseCfg(V, cfgSgmac0RxPfcPriorityEn_f, &ds, field_val);
                    SetSgmac0RxPauseCfg(V, cfgSgmac0RxNormPauseEn_f, &ds, 0);
                }
                else
                {
                    SetSgmac0RxPauseCfg(V, cfgSgmac0RxNormPauseEn_f, &ds, (fc_prop->enable) ? 1 : 0);
                    SetSgmac0RxPauseCfg(V, cfgSgmac0RxPfcPauseEn_f, &ds, 0);
                    SetSgmac0RxPauseCfg(V, cfgSgmac0RxPfcPriorityEn_f, &ds, 0);
                }
                cmd = DRV_IOW(Sgmac0RxPauseCfg_t + step, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds));
            }
            else
            {
                step = (McMacPauseRxCtl_mcMacPauseRxCfg_1_cfgMcMacRxPfcPauseEn_f - McMacPauseRxCtl_mcMacPauseRxCfg_0_cfgMcMacRxPfcPauseEn_f)
                * (mac_id % MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM));

                /*FC/PFC enable/disable*/
                cmd = DRV_IOR(McMacPauseRxCtl_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, mac_id / MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM), cmd, &mac_rx_pause_ctl));

                old_is_pfc = GetMcMacPauseRxCtl(V, mcMacPauseRxCfg_0_cfgMcMacRxPfcPauseEn_f + step, &mac_rx_pause_ctl);
                old_is_fc = GetMcMacPauseRxCtl(V, mcMacPauseRxCfg_0_cfgMcMacRxNormPauseEn_f + step, &mac_rx_pause_ctl);

                if (!fc_prop->enable && ((fc_prop->is_pfc && old_is_fc) || (!fc_prop->is_pfc && old_is_pfc) || (!old_is_pfc && !old_is_fc)))
                {
                    return CTC_E_NONE;
                }
        
                if (fc_prop->is_pfc)
                {
                    SetMcMacPauseRxCtl(V, mcMacPauseRxCfg_0_cfgMcMacRxPfcPauseEn_f + step, &mac_rx_pause_ctl, 1);
                    field_val = GetMcMacPauseRxCtl(V, mcMacPauseRxCfg_0_cfgMcMacRxPfcPriorityEn_f + step, &mac_rx_pause_ctl);
                    fc_prop->enable ? CTC_BIT_SET(field_val, pfc_class) : CTC_BIT_UNSET(field_val, pfc_class);
                    SetMcMacPauseRxCtl(V, mcMacPauseRxCfg_0_cfgMcMacRxPfcPriorityEn_f + step, &mac_rx_pause_ctl, field_val);
                    SetMcMacPauseRxCtl(V, mcMacPauseRxCfg_0_cfgMcMacRxNormPauseEn_f + step, &mac_rx_pause_ctl, 0);
                }
                else
                {
                    field_val = (fc_prop->enable) ? 1 : 0;
                    SetMcMacPauseRxCtl(V, mcMacPauseRxCfg_0_cfgMcMacRxNormPauseEn_f + step, &mac_rx_pause_ctl, field_val);
                    SetMcMacPauseRxCtl(V, mcMacPauseRxCfg_0_cfgMcMacRxPfcPauseEn_f + step, &mac_rx_pause_ctl, 0);
                    SetMcMacPauseRxCtl(V, mcMacPauseRxCfg_0_cfgMcMacRxPfcPriorityEn_f + step, &mac_rx_pause_ctl, 0);
                }
            }
            
            cmd = DRV_IOW(McMacPauseRxCtl_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, mac_id / MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM), cmd, &mac_rx_pause_ctl));

            if ((old_is_pfc && !fc_prop->is_pfc) || fc_prop->is_pfc)
            {
                /*config group flowctl enable*/
                if (MCHIP_QOS(lchip)->qos_sch_update_fc_group)
                {
                    CTC_ERROR_RETURN(MCHIP_QOS(lchip)->qos_sch_update_fc_group(lchip, chan_id1, 0, 0, (field_val && fc_prop->is_pfc) ? 1 : 0));
                }
            }

            if (old_is_pfc && !fc_prop->is_pfc)
            {
                field_val = 0;
                cmd = DRV_IOW(DsQMgrFlowCtlState_t, DsQMgrFlowCtlState_stallValid_f);
                CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, chan_id1, cmd, &field_val));
            }
        }
        
        /*pfc/fc enable/disable and dynamic switch*/
        if ((CTC_EGRESS == fc_prop->dir) || (CTC_BOTH_DIRECTION == fc_prop->dir))
        {
            step = (McMacPauseTxCtl_mcMacPauseTxCfg_1_cfgMcMacTxPauseType_f - McMacPauseTxCtl_mcMacPauseTxCfg_0_cfgMcMacTxPauseType_f)
                     * (mac_id % MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM));
            /*get old Irm FC/PFC enable/disable*/
            cmd = DRV_IOR(DsIrmPortStallEn_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, chan_id, cmd, &irm_stall_en));
            old_is_pfc = GetDsIrmPortStallEn(V, portPriEnVec_f, &irm_stall_en);
            old_is_fc = GetDsIrmPortStallEn(V, portFcEn_f, &irm_stall_en) && !old_is_pfc;
            if(!fc_prop->enable && ((fc_prop->is_pfc && old_is_fc) || (!fc_prop->is_pfc && old_is_pfc) || (!old_is_pfc && !old_is_fc)))
            {
                return CTC_E_NONE;
            }
            if (fc_prop->enable && ((fc_prop->is_pfc && old_is_fc) || (!fc_prop->is_pfc && old_is_pfc)))
            {
                /*switch_1 :config netrx: do not response to IRM request*/
                cmd = DRV_IOR(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, dp_id, cmd, &net_rx_pause_ctl));
                GetNetRxPauseReqCtl(A, bsPauseMaskBmp_f, &net_rx_pause_ctl, rx_pause_type);
                CTC_BIT_SET(rx_pause_type[tmp_chan >> 5], (tmp_chan&0x1F));
                SetNetRxPauseReqCtl(A, bsPauseMaskBmp_f, &net_rx_pause_ctl, rx_pause_type);
                cmd = DRV_IOW(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, dp_id, cmd, &net_rx_pause_ctl));
            }
            if (!fc_prop->enable || (fc_prop->is_pfc && old_is_fc) || (!fc_prop->is_pfc && old_is_pfc))
            {
                if (!fc_prop->enable)
                {
                    /*diable_1:config IRM*/
                    if (fc_prop->is_pfc)
                    {
                        field_val = old_is_pfc & (~(1 << fc_prop->priority_class));
                        egs_pfc_en = field_val ? 1 : 0;
                        cmd = DRV_IOW(DsIrmPortStallEn_t, DsIrmPortStallEn_portPriEnVec_f);
                        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, chan_id, cmd, &field_val));
                    }
                    if((old_is_pfc && fc_prop->is_pfc && !field_val) || 
                        (old_is_fc && !fc_prop->is_pfc))

                    {
                        field_val = 0;
                        cmd = DRV_IOW(DsIrmPortStallEn_t, DsIrmPortStallEn_portFcEn_f);
                        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, chan_id, cmd, &field_val));
                    }
                }
                /*switch_2/diable_2:clear port xoff status*/
                sal_memset(&netrx_pause_stats, 0, sizeof(DsNetRxPauseStats_m));
                SetDsNetRxPauseStats(V,pauseStatsWrEn_f,&netrx_pause_stats,1);
                SetDsNetRxPauseStats(V,pauseStatsPort_f,&netrx_pause_stats,lmac_id);
                SetDsNetRxPauseStats(V,pauseStatsStallVec_f,&netrx_pause_stats,(!fc_prop->enable ? (fc_prop->is_pfc ? 1 << fc_prop->priority_class : 0xff) : (fc_prop->is_pfc ? 0x1 : 0xff)));
                cmd = DRV_IOW(DsNetRxPauseStats_t,DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, dp_id, cmd, &netrx_pause_stats));

                /*switch_3/diable_3:force mac sending xon pause*/
                field_val = lmac_id;
                cmd = DRV_IOW(NetRxForcePauseReq_t, NetRxForcePauseReq_cfgForcePauseReqPortId_f);
                CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, dp_id, cmd, &field_val));

                if (!fc_prop->enable)
                {
                    if (old_is_fc || (old_is_pfc && !egs_pfc_en))
                    {
                        field_val = 0;
                        cmd = DRV_IOW(McMacPauseTxCtl_t, McMacPauseTxCtl_mcMacPauseTxCfg_0_dbgMcMacTxPauseCurStatus_f + step);
                        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, mac_id / MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM), cmd, &field_val));
                        cmd = DRV_IOW(McMacPauseTxCtl_t, McMacPauseTxCtl_mcMacPauseTxCfg_0_dbgMcMacTxPauseLogStatus_f + step);
                        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, mac_id / MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM), cmd, &field_val));
                    }
                    return CTC_E_NONE;
                }
            }

            field_val = fc_prop->is_pfc ? (old_is_pfc | 1 << fc_prop->priority_class) : 0;
            cmd = DRV_IOW(DsIrmPortStallEn_t, DsIrmPortStallEn_portPriEnVec_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, chan_id, cmd, &field_val));
            field_val = fc_prop->enable ? 1 : 0;
            cmd = DRV_IOW(DsIrmPortStallEn_t, DsIrmPortStallEn_portFcEn_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, chan_id, cmd, &field_val));

            /*switch_4/enable_1:change pause type*/
            if(!((fc_prop->is_pfc && old_is_pfc) || (!fc_prop->is_pfc && old_is_fc)))
            {
                cmd = DRV_IOR(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, dp_id, cmd, &net_rx_pause_ctl));
                GetNetRxPauseReqCtl(A, netRxPauseType_f, &net_rx_pause_ctl, rx_pause_type);
                if (fc_prop->is_pfc && fc_prop->enable)
                {
                    CTC_BIT_SET(rx_pause_type[lmac_id >> 5], (lmac_id&0x1F));
                }
                else if ( !fc_prop->is_pfc && fc_prop->enable)
                {
                    CTC_BIT_UNSET(rx_pause_type[lmac_id >> 5], (lmac_id&0x1F));
                }
                SetNetRxPauseReqCtl(A, netRxPauseType_f, &net_rx_pause_ctl, rx_pause_type);
                cmd = DRV_IOW(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, dp_id, cmd, &net_rx_pause_ctl));

                field_val = fc_prop->is_pfc ? 1 : 0;
                if (DRV_IS_TMG(lchip))
                {
                    step = (Sgmac1TxPauseCfg_t - Sgmac0TxPauseCfg_t) * (mac_id % MCHIP_CAP(SYS_CAP_STATS_XQMAC_PORT_NUM));
                    index = mac_id / MCHIP_CAP(SYS_CAP_STATS_XQMAC_PORT_NUM);
                    cmd = DRV_IOR(Sgmac0TxPauseCfg_t + step, DRV_ENTRY_FLAG);
                    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds));
                    SetSgmac0TxPauseCfg(V, cfgSgmac0TxPauseType_f, &ds, field_val);
                    cmd = DRV_IOW(Sgmac0TxPauseCfg_t + step, DRV_ENTRY_FLAG);
                    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds));
                }
                else
                {
                    cmd = DRV_IOW(McMacPauseTxCtl_t, McMacPauseTxCtl_mcMacPauseTxCfg_0_cfgMcMacTxPauseType_f + step);
                    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, mac_id / MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM), cmd, &field_val));
                }

                if (fc_prop->enable && ((fc_prop->is_pfc && old_is_fc) || (!fc_prop->is_pfc && old_is_pfc)))
                {
                    /*switch_5:config netrx: response to IRM request*/
                    cmd = DRV_IOR(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
                    CTC_ERROR_RETURN(DRV_IOCTL(lchip, dp_id, cmd, &net_rx_pause_ctl));
                    GetNetRxPauseReqCtl(A, bsPauseMaskBmp_f, &net_rx_pause_ctl, rx_pause_type);
                    CTC_BIT_UNSET(rx_pause_type[tmp_chan >> 5], (tmp_chan&0x1F));
                    SetNetRxPauseReqCtl(A, bsPauseMaskBmp_f, &net_rx_pause_ctl, rx_pause_type);
                    cmd = DRV_IOW(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
                    CTC_ERROR_RETURN(DRV_IOCTL(lchip, dp_id, cmd, &net_rx_pause_ctl));
                }
            }
        }
    }
    return CTC_E_NONE;
}

int32
sys_tmm_port_get_flow_ctl_en(uint8 lchip, void* p_fc_prop)
{
    uint8 dp_id = 0;
    uint8 lmac_id = 0;
    uint32 chan_id = 0; /*egress chan*/
    uint32 chan_id1 = 0; /*ingress chan*/
    uint16 step = 0;
    uint32 mac_id = 0;
    uint32 cmd = 0;
    uint32 field_val = 0;
    uint32 rx_pause_type[5] = {0};
    uint32 index = 0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};
    NetRxPauseReqCtl_m  net_rx_pause_ctl;
    McMacPauseRxCtl_m mac_rx_pause_ctl;
    DsIrmPortStallEn_m  irm_stall_en;
    ctc_port_fc_prop_t *fc_prop = (ctc_port_fc_prop_t *)p_fc_prop;
    uint32 cpumac_pause_type = 0;
    ds_t  ds;

    sal_memset(&ds, 0, sizeof(ds));
    sal_memset(&irm_stall_en, 0, sizeof(DsIrmPortStallEn_m));
    sal_memset(&net_rx_pause_ctl, 0, sizeof(NetRxPauseReqCtl_m));
    sal_memset(&mac_rx_pause_ctl, 0, sizeof(McMacPauseRxCtl_m));
    CTC_MAX_VALUE_CHECK(fc_prop->priority_class, SYS_PORT_PRIO_CLASS_NUM - 1);
    if(fc_prop->is_oobfc || CTC_PORT_FC_TYPE_OOB == fc_prop->type)
    {
        return DRV_IS_TMG(lchip) ? CTC_E_NOT_SUPPORT : sys_tmm_port_get_oobfc_en(lchip, fc_prop);
    }
    dmps_port_info.gport = fc_prop->gport;
    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_MAC_ID, (void *)&mac_id));
    if (0xff == mac_id)
    {
        return CTC_E_INVALID_CONFIG;
    }

    if(CTC_PORT_FC_TYPE_OBM == fc_prop->type)
    {
        return DRV_IS_TMG(lchip) ? _sys_tmm_port_get_obmfc_en2(lchip, mac_id, fc_prop)
                                 : _sys_tmm_port_get_obmfc_en(lchip, mac_id, fc_prop);
    }
    /*for xpipe
     *pfc ingress : back pressure to low priority chan
     *pfc egress  : CTC_PORT_XPIPE_TYPE_1/CTC_PORT_XPIPE_TYPE_3 triggered by high priority chan, else low priority chan.
     */
    CTC_ERROR_RETURN(sys_usw_port_get_property(lchip, fc_prop->gport, CTC_PORT_PROP_XPIPE_EN, &field_val)); 
    if(field_val && !CTC_IS_MCHAN_PORT(fc_prop->gport))
    {
        CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_GET_PMAC_CHAN_ID, &chan_id));          /*high priority chan*/
        CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &chan_id1));  /*low priority chan*/
        chan_id = (field_val == CTC_PORT_XPIPE_TYPE_1 || field_val == CTC_PORT_XPIPE_TYPE_3 || field_val == CTC_PORT_XPIPE_TYPE_6) ? chan_id : chan_id1; /*CTC_PORT_XPIPE_TYPE_2 low, else high*/
    }
    else
    {
        CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &chan_id));
        chan_id1 = chan_id; /*low*/
    }
    if (SYS_COMMON_USELESS_CHANNEL == chan_id1 || SYS_COMMON_USELESS_CHANNEL == chan_id)
    {
        return CTC_E_INVALID_CONFIG;
    }

    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_SPEED_MODE, (void *)&field_val));
    if (DRV_IS_TMM(lchip) && (SYS_GET_CHIP_VERSION == SYS_CHIP_SUB_VERSION_A) && field_val <= CTC_PORT_SPEED_2G5)
    {
        return CTC_E_NOT_SUPPORT;
    }

    if (mac_id >= SYS_CPU_MAC_ID_MIN && mac_id <= SYS_CPU_MAC_ID_MAX)
    {
        dp_id = (mac_id - SYS_CPU_MAC_ID_MIN) / MCHIP_CAP(SYS_CAP_CPUMAC_NUM_PER_DP);
        /*Rx port set pause type: fc/pfc*/
        cmd = DRV_IOR(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, dp_id, cmd, &net_rx_pause_ctl));
        cpumac_pause_type = GetNetRxPauseReqCtl(V, cfgCpuMacPauseType_f, &net_rx_pause_ctl);
        if (CTC_INGRESS == fc_prop->dir)
        {
            /*FC/PFC enable/disable*/
            step = (Sgmac1RxPauseCfg_t - Sgmac0RxPauseCfg_t) * (mac_id - SYS_CPU_MAC_ID_MIN);
            index = DRV_IS_TMG(lchip) ? mac_id / MCHIP_CAP(SYS_CAP_STATS_XQMAC_PORT_NUM) : 0;
            cmd = DRV_IOR(Sgmac0RxPauseCfg_t + step, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds));
            field_val = GetSgmac0RxPauseCfg(V, cfgSgmac0RxPfcPriorityEn_f, &ds);

            if (fc_prop->is_pfc && CTC_IS_BIT_SET(field_val, fc_prop->pfc_class)
                && CTC_IS_BIT_SET(cpumac_pause_type, ((mac_id - SYS_CPU_MAC_ID_MIN)&0x1)))
            {
                fc_prop->enable = GetSgmac0RxPauseCfg(V, cfgSgmac0RxPfcPauseEn_f, &ds);
                CTC_ERROR_RETURN(_sys_tmm_port_get_igs_flow_ctl_map(lchip, chan_id1, fc_prop));
            }
            else if(!fc_prop->is_pfc && !CTC_IS_BIT_SET(cpumac_pause_type, ((mac_id - SYS_CPU_MAC_ID_MIN)&0x1)))
            {
                fc_prop->enable = GetSgmac0RxPauseCfg(V, cfgSgmac0RxNormPauseEn_f, &ds);
            }
        }
        /* egress only global contral */
        if (CTC_EGRESS == fc_prop->dir)
        {
            /*Irm FC/PFC enable/disable*/
            cmd = DRV_IOR(DsIrmPortStallEn_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, chan_id, cmd, &irm_stall_en));
            if (fc_prop->is_pfc && CTC_IS_BIT_SET(cpumac_pause_type, ((mac_id - SYS_CPU_MAC_ID_MIN)&0x1)))
            {
                field_val = GetDsIrmPortStallEn(V, portPriEnVec_f, &irm_stall_en);
                fc_prop->enable = CTC_IS_BIT_SET(field_val, (fc_prop->priority_class));
            }
            else if(!fc_prop->is_pfc && !CTC_IS_BIT_SET(cpumac_pause_type, ((mac_id - SYS_CPU_MAC_ID_MIN)&0x1)))
            {
                field_val = GetDsIrmPortStallEn(V, portFcEn_f, &irm_stall_en);
                fc_prop->enable = field_val;
            }
        }
    }
    else
    {
        if (CTC_INGRESS == fc_prop->dir)
        {
            /*FC/PFC enable/disable*/
            if (DRV_IS_TMG(lchip))
            {
                step = (Sgmac1RxPauseCfg_t - Sgmac0RxPauseCfg_t) * (mac_id % MCHIP_CAP(SYS_CAP_STATS_XQMAC_PORT_NUM));
                index = mac_id / MCHIP_CAP(SYS_CAP_STATS_XQMAC_PORT_NUM);
                cmd = DRV_IOR(Sgmac0RxPauseCfg_t + step, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &ds));
                field_val = GetSgmac0RxPauseCfg(V, cfgSgmac0RxPfcPriorityEn_f, &ds);
                if (fc_prop->is_pfc && CTC_IS_BIT_SET(field_val, fc_prop->pfc_class)
                    && CTC_IS_BIT_SET(rx_pause_type[lmac_id >> 5], (lmac_id&0x1F)))
                {
                    fc_prop->enable = GetSgmac0RxPauseCfg(V, cfgSgmac0RxPfcPauseEn_f, &ds);
                }
                else if(!fc_prop->is_pfc && !CTC_IS_BIT_SET(rx_pause_type[lmac_id >> 5], (lmac_id&0x1F)))
                {
                    fc_prop->enable = GetSgmac0RxPauseCfg(V, cfgSgmac0RxNormPauseEn_f, &ds);
                }
            }
            else
            {
                step = (McMacPauseRxCtl_mcMacPauseRxCfg_1_cfgMcMacRxPfcPauseEn_f - McMacPauseRxCtl_mcMacPauseRxCfg_0_cfgMcMacRxPfcPauseEn_f)
                * (mac_id % MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM));
                cmd = DRV_IOR(McMacPauseRxCtl_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip, mac_id / MCHIP_CAP(SYS_CAP_MAC_NUM_PER_QM), cmd, &mac_rx_pause_ctl));
                field_val = GetMcMacPauseRxCtl(V, mcMacPauseRxCfg_0_cfgMcMacRxPfcPriorityEn_f + step, &mac_rx_pause_ctl);

                if (fc_prop->is_pfc && CTC_IS_BIT_SET(field_val, fc_prop->pfc_class))
                {
                    fc_prop->enable = GetMcMacPauseRxCtl(V, mcMacPauseRxCfg_0_cfgMcMacRxPfcPauseEn_f + step, &mac_rx_pause_ctl);
                    CTC_ERROR_RETURN(_sys_tmm_port_get_igs_flow_ctl_map(lchip, chan_id1, fc_prop));
                }
                else if (!fc_prop->is_pfc)
                {
                    fc_prop->enable = GetMcMacPauseRxCtl(V, mcMacPauseRxCfg_0_cfgMcMacRxNormPauseEn_f + step, &mac_rx_pause_ctl);
                }
            }
        }
        
        /* egress only global contral */
        if (CTC_EGRESS == fc_prop->dir)
        {
            dp_id = mac_id / MCHIP_CAP(SYS_CAP_MAC_NUM_PER_DP);
            lmac_id = mac_id % MCHIP_CAP(SYS_CAP_MAC_NUM_PER_DP);

            cmd = DRV_IOR(NetRxPauseReqCtl_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, dp_id, cmd, &net_rx_pause_ctl));
            GetNetRxPauseReqCtl(A, netRxPauseType_f, &net_rx_pause_ctl, rx_pause_type);

            /*Irm FC/PFC enable/disable*/
            cmd = DRV_IOR(DsIrmPortStallEn_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, chan_id, cmd, &irm_stall_en));
            if (fc_prop->is_pfc && CTC_IS_BIT_SET(rx_pause_type[lmac_id >> 5], (lmac_id&0x1F)))
            {
                field_val = GetDsIrmPortStallEn(V, portPriEnVec_f, &irm_stall_en);
                fc_prop->enable = CTC_IS_BIT_SET(field_val, (fc_prop->priority_class));
            }
            else if(!fc_prop->is_pfc && !CTC_IS_BIT_SET(rx_pause_type[lmac_id >> 5], (lmac_id&0x1F)))
            {
                field_val = GetDsIrmPortStallEn(V, portFcEn_f, &irm_stall_en);
                fc_prop->enable = field_val;
            }
        }
    }
    return CTC_E_NONE;
}

/*
brief cfg xpipe rx prop
*/
int32
sys_tmm_port_set_xpipe_en(uint8 lchip, uint32 gport, uint32 value)
{
    uint8   dp_id            = 0;
    uint8   txqm_id          = 0;
    uint8   mac_num          = 0;
    uint8   chan_num         = 0;
    uint32  emac_id_per_txqm = 0;
    uint32  pmac_id_per_txqm = 0;
    uint32  pmac_id          = 0;
    uint32  pmac_channel_id  = 0;
    uint32  emac_id          = 0;
    uint32  emac_channel_id  = 0;
    uint32  step             = 0;
    uint32  tmp_value        = 0;
    uint32  old_type         = 0;
    uint32  cmd              = 0;
    uint32  enable[5]        = {0};
    uint32  emac_id_per_dp   = 0;
    uint32  split_en[2]      = {0};
    uint32  srcGuaranteeEn[32] = {0};
    uint32  channel[SYS_USW_MAX_CHANEL_NUM_PER_PORT] = {0};    /* 0: low prio channel(origin channel), 1: high prio channel */
    uint32  mac_id[SYS_USW_MAX_CHANEL_NUM_PER_PORT]  = {0};    /* 0: low prio mac, 1: high prio mac(origin mac) */
    ds1_t   ds;
    DsNetRxBufAdmissionCtl_m adm_ctl;

    sal_memset(&ds, 0, sizeof(ds1_t));
    sal_memset(&adm_ctl, 0, sizeof(DsNetRxBufAdmissionCtl_m));

    old_type = p_usw_port_master[lchip]->port_prop[CTC_MAP_GPORT_TO_LPORT(gport)].xpipe_type;
    CTC_ERROR_RETURN(sys_usw_port_api_get_mac(lchip, 0, gport, mac_id, &mac_num));
    CTC_ERROR_RETURN(sys_usw_port_api_get_channel(lchip, 0, gport, channel, &chan_num));

    emac_id = mac_id[mac_num-1];
    pmac_id = mac_id[0];
    emac_channel_id = channel[chan_num -1];
    pmac_channel_id = channel[0];

    /*Xpipe use for TM.MX NetRx, support pfc back pressure low priority chan, low channel and high has switch, emac_id-->pmac_chanel_id, pmac_id-->emac_chanel_id*/

    emac_id_per_dp   =  emac_id % MCHIP_CAP(SYS_CAP_MAX_MAC_NUM_PER_DP);
    pmac_id_per_txqm =  pmac_id % MCHIP_CAP(SYS_CAP_MAX_MAC_NUM_PER_TXQM);
    emac_id_per_txqm =  emac_id % MCHIP_CAP(SYS_CAP_MAX_MAC_NUM_PER_TXQM);
    dp_id = (MCHIP_CAP(SYS_CAP_MAX_MAC_NUM) <= emac_id) ? ((emac_id - MCHIP_CAP(SYS_CAP_MAX_MAC_NUM)) / MCHIP_CAP(SYS_CAP_CPUMAC_NUM_PER_DP)) : (emac_id / MCHIP_CAP(SYS_CAP_MAX_MAC_NUM_PER_DP));
    txqm_id          = (emac_id / MCHIP_CAP(SYS_CAP_MAX_MAC_NUM_PER_TXQM)) - (dp_id * MCHIP_CAP(SYS_CAP_TXQM_NUM_PER_DP));

    SYS_PORT_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "emac id: %d, emac channel: %d, pmac id: %d, pmac channel: %d\n", emac_id, emac_channel_id, pmac_id, pmac_channel_id);
    SYS_PORT_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "dp id: %d, txqm id: %d, emac id per txqm: %d, pmac id per txqm: %d\n", dp_id, txqm_id, emac_id_per_txqm, pmac_id_per_txqm);

    /*1. cfg netRx split */
    step = NetRxPortSplitEnCtl_portSplitEn1_f - NetRxPortSplitEnCtl_portSplitEn0_f;
    cmd = DRV_IOR(NetRxPortSplitEnCtl_t, NetRxPortSplitEnCtl_portSplitEn0_f+step * txqm_id);
    DRV_FIELD_IOCTL(lchip, dp_id, cmd, split_en);
    value ? CTC_BIT_SET(split_en[emac_id_per_txqm / BITS_NUM_OF_WORD], emac_id_per_txqm % BITS_NUM_OF_WORD):
          CTC_BIT_UNSET(split_en[emac_id_per_txqm / BITS_NUM_OF_WORD], emac_id_per_txqm % BITS_NUM_OF_WORD);
    cmd = DRV_IOW(NetRxPortSplitEnCtl_t, NetRxPortSplitEnCtl_portSplitEn0_f+step * txqm_id);
    DRV_FIELD_IOCTL(lchip, dp_id, cmd, split_en);

    /*1.1 set mac to chan map */
    step = DsNetRxPriorityChannelRemap1_t - DsNetRxPriorityChannelRemap0_t;
    cmd = DRV_IOW(DsNetRxPriorityChannelRemap0_t+step * txqm_id, DsNetRxPriorityChannelRemap0_port_f);
    DRV_FIELD_IOCTL(lchip, dp_id*MCHIP_CAP(SYS_CAP_MAX_MAC_NUM_PER_TXQM) + emac_id_per_txqm, cmd, &pmac_id_per_txqm);
    if (CTC_PORT_XPIPE_TYPE_6 != value && CTC_PORT_XPIPE_TYPE_6 != old_type)
    {
        /*2. set srcGuaranteeEn and destGuaranteeChannel */
        cmd = DRV_IOR(QWriteGuaranteeCtl_t, QWriteGuaranteeCtl_srcGuaranteeEn_f);
        DRV_FIELD_IOCTL(lchip, 0, cmd, srcGuaranteeEn);

        if (value)
        {
            if (value == CTC_PORT_XPIPE_TYPE_2)
            {
                CTC_BIT_UNSET(srcGuaranteeEn[pmac_channel_id / BITS_NUM_OF_WORD], pmac_channel_id % BITS_NUM_OF_WORD);
                CTC_BIT_SET(srcGuaranteeEn[emac_channel_id / BITS_NUM_OF_WORD], emac_channel_id % BITS_NUM_OF_WORD);
            }
            else
            {
                CTC_BIT_UNSET(srcGuaranteeEn[emac_channel_id / BITS_NUM_OF_WORD], emac_channel_id % BITS_NUM_OF_WORD);
                CTC_BIT_SET(srcGuaranteeEn[pmac_channel_id / BITS_NUM_OF_WORD], pmac_channel_id % BITS_NUM_OF_WORD);
            }
        }
        else
        {
            CTC_BIT_SET(srcGuaranteeEn[emac_channel_id / BITS_NUM_OF_WORD], emac_channel_id % BITS_NUM_OF_WORD);
        }
        cmd = DRV_IOW(QWriteGuaranteeCtl_t, QWriteGuaranteeCtl_srcGuaranteeEn_f);
        DRV_FIELD_IOCTL(lchip, 0, cmd, srcGuaranteeEn);

        /*3. classify base on preamble*/
        tmp_value = (CTC_PORT_XPIPE_TYPE_1 ==value || CTC_PORT_XPIPE_TYPE_3 == value) ? 1 : 0;
        CTC_ERROR_RETURN(sys_usw_dmps_set_port_property(lchip, gport, SYS_PORT_API_DMPS_PROP_RX_PMAC_SFD_ENABLE, (void *)&tmp_value));
        CTC_ERROR_RETURN(sys_usw_dmps_set_port_property(lchip, gport, SYS_PORT_API_DMPS_PROP_TX_PMAC_SFD_ENABLE, (void *)&tmp_value));

        /*4. cfg nettx split and recod pmac id */
        step = NetTxPortSplitEnCtl_portSplitEn1_f - NetTxPortSplitEnCtl_portSplitEn0_f;
        cmd = DRV_IOR(NetTxPortSplitEnCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, dp_id, cmd, ds));
        GetNetTxPortSplitEnCtl(A, portSplitEn0_f + step * txqm_id, ds, split_en);
        value? CTC_BIT_SET(split_en[emac_id_per_txqm/BITS_NUM_OF_WORD], emac_id_per_txqm%BITS_NUM_OF_WORD): 
            CTC_BIT_UNSET(split_en[emac_id_per_txqm/BITS_NUM_OF_WORD], emac_id_per_txqm%BITS_NUM_OF_WORD);
        SetNetTxPortSplitEnCtl(A, portSplitEn0_f + step * txqm_id, ds, split_en);
        cmd = DRV_IOW(NetTxPortSplitEnCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, dp_id, cmd, ds));

        sal_memset(ds, 0, sizeof(ds));
        SetDsNetTxPriorityPortRemap0(V, port_f, &ds, pmac_id_per_txqm);
        step = DsNetTxPriorityPortRemap1_t - DsNetTxPriorityPortRemap0_t;
        cmd = DRV_IOW(DsNetTxPriorityPortRemap0_t+step * txqm_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, dp_id*MCHIP_CAP(SYS_CAP_MAX_MAC_NUM_PER_TXQM) + emac_id_per_txqm, cmd, ds));

        /*5. cfg redirect channel */
        cmd = DRV_IOR(DsQWriteGuarantee_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, pmac_channel_id, cmd, ds))
        SetDsQWriteGuarantee(V, destGuaranteeChannel_f, &ds, emac_channel_id);
        cmd = DRV_IOW(DsQWriteGuarantee_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, pmac_channel_id, cmd, ds))
    }

    /*5. classify base on fields*/
    tmp_value = (value == CTC_PORT_XPIPE_TYPE_2 || value == CTC_PORT_XPIPE_TYPE_6) ? 1 : 0;
    cmd = DRV_IOR(NetRxPriorityChannelEn_t, NetRxPriorityChannelEn_enable_f);
    DRV_FIELD_IOCTL(lchip, dp_id, cmd, enable);
    tmp_value ? CTC_BIT_SET(enable[emac_id_per_dp / BITS_NUM_OF_WORD], emac_id_per_dp % BITS_NUM_OF_WORD):
              CTC_BIT_UNSET(enable[emac_id_per_dp / BITS_NUM_OF_WORD], emac_id_per_dp % BITS_NUM_OF_WORD);
    cmd = DRV_IOW(NetRxPriorityChannelEn_t, NetRxPriorityChannelEn_enable_f);
    DRV_FIELD_IOCTL(lchip, dp_id, cmd, enable);

    if (CTC_PORT_XPIPE_TYPE_3 == value)
    {
        tmp_value = SYS_USW_XPIPE_RSV_PORT;
        cmd = DRV_IOW(IpeHeaderAdjustPhyPortMap_t, IpeHeaderAdjustPhyPortMap_localPhyPort_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, pmac_channel_id, cmd, &tmp_value));
    }

    return CTC_E_NONE;
}
/*
brief cfg xpipe tx prop
*/
int32
sys_tmm_port_set_xpipe_mode(uint8 lchip, uint32 gport, uint32 value)
{
    ds1_t  ds               = {0};
    uint32 channel[SYS_USW_MAX_CHANEL_NUM_PER_PORT] = {0};    /* 0: low prio channel(origin channel), 1: high prio channel */
    uint32 cmd              = 0;
    uint32 mode             = 0;
    uint32 pmac_channel_id  = 0;
    uint8  chan_num         = 0;

    sal_memset(&ds, 0, sizeof(ds1_t));

    CTC_ERROR_RETURN(sys_usw_port_api_get_channel(lchip, 1, gport, channel, &chan_num));


    SYS_PORT_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "emac channel: %d, pmac channel: %d\n",  channel[1], channel[0]);
    pmac_channel_id = channel[0];

    if (CTC_XPIPE_MODE_0 == value || CTC_XPIPE_MODE_1 == value)
    {
        mode = 0;
    }
    else if (CTC_XPIPE_MODE_2 == value)
    {
        mode = 1;
    }
    else
    {
        mode = 3;
    }

    cmd = DRV_IOR(DsQWriteGuarantee_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, pmac_channel_id, cmd, ds))
    SetDsQWriteGuarantee(V, mode_f, &ds, mode);
    cmd = DRV_IOW(DsQWriteGuarantee_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, pmac_channel_id, cmd, ds))

    return CTC_E_NONE;
}

#endif

